package com.xxx.car.service.impl;

import com.github.pagehelper.PageHelper;
import com.xxx.car.entity.TbRedpacketRecord;
import com.xxx.car.entity.TbUserWallet;
import com.xxx.car.entity.vo.request.ReqRedpackageDetail;
import com.xxx.car.entity.vo.request.ReqRedpackageWithdraw;
import com.xxx.car.entity.vo.response.RespRedPackageDetail;
import com.xxx.car.entity.vo.response.RespUserWallet;
import com.xxx.car.mapper.ITbMapper;
import com.xxx.car.mapper.TbRedpacketRecordMapper;
import com.xxx.car.mapper.TbUserWalletMapper;
import com.xxx.car.service.UserWalletService;
import com.xxx.common.base.exception.BizException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by xuwenjie on 2017/6/16.
 */
@Service
public class UserWalletServiceImpl implements UserWalletService {

    private final static Logger LOG = LoggerFactory.getLogger(UserWalletServiceImpl.class);

    private final static BigDecimal MIN_WITHDRAW_AMT = new BigDecimal(10);

    @Autowired
    private TbUserWalletMapper tbUserWalletMapper;

    @Autowired
    private TbRedpacketRecordMapper tbRedpacketRecordMapper;

    @Autowired
    private ITbMapper iTbMapper;

    @Override
    public RespUserWallet getByUser(Integer userId) {
        TbUserWallet wallet = tbUserWalletMapper.selectByPrimaryKey(userId);
        RespUserWallet respUserWallet = new RespUserWallet();
        if (wallet != null) {
            BeanUtils.copyProperties(wallet, respUserWallet);
        } else {
            respUserWallet.setUserId(userId);
        }
        return respUserWallet;
    }

    @Override
    @Transactional
    public void changeAmt(Integer userId, long chargeAmt, BigDecimal redPackageAmt, long giveAmt, long bonusPoints) {
        TbUserWallet tbUserWallet = lockWallet(userId);
        if (tbUserWallet.getChargeAmt() + chargeAmt < 0) {
            throw new BizException("chargeAmt超限");
        }
        if (tbUserWallet.getGiveAmt() + giveAmt < 0) {
            throw new BizException("giveAmt超限");
        }
        if (tbUserWallet.getBonusPoints() + bonusPoints < 0) {
            throw new BizException("bonusPoints超限");
        }
        tbUserWalletMapper.changeAmt(userId, chargeAmt, redPackageAmt, giveAmt, bonusPoints);
    }

    @Override
    @Transactional
    public void redpackageWithdraw(ReqRedpackageWithdraw reqRedpackageWithdraw) {
        TbUserWallet tbUserWallet = lockWallet(reqRedpackageWithdraw.getUserId());
        if (tbUserWallet == null) {
            throw new BizException("金额异常");
        }
        BigDecimal withdrawAmt = tbUserWallet.getRedPackageAmt();
        if (tbUserWallet.getRedPackageAmt().compareTo(MIN_WITHDRAW_AMT) < 0) {
            throw new BizException("金额不足无法提现");
        }
        if (reqRedpackageWithdraw.getWithDrawAmt() != null) {
            if (reqRedpackageWithdraw.getWithDrawAmt().compareTo(MIN_WITHDRAW_AMT) < 0) {
                throw new BizException("提现金额小于最小值");
            } else {
                withdrawAmt = reqRedpackageWithdraw.getWithDrawAmt();
            }
        }
        tbUserWalletMapper.changeAmt(reqRedpackageWithdraw.getUserId(), withdrawAmt.multiply(new BigDecimal(100)).longValue(), BigDecimal.ZERO.subtract(withdrawAmt),0L, 0L);
        TbRedpacketRecord redpackageWithdrawLog = new TbRedpacketRecord();
        Date now = new Date();
        redpackageWithdrawLog.setCreateTime(now);
        redpackageWithdrawLog.setUpdateTime(now);
        redpackageWithdrawLog.setUserId(reqRedpackageWithdraw.getUserId());
        redpackageWithdrawLog.setAmount(BigDecimal.ZERO.subtract(withdrawAmt));
        redpackageWithdrawLog.setStatus((byte)0);
        tbRedpacketRecordMapper.insertSelective(redpackageWithdrawLog);
    }

    @Override
    public List<RespRedPackageDetail> listRedPackageDetail(ReqRedpackageDetail reqRedpackageDetail) {
        PageHelper.startPage(reqRedpackageDetail.getPageNum(), reqRedpackageDetail.getPageSize());
        return iTbMapper.queryRedPackageDetail(reqRedpackageDetail).stream().map(e -> {
            RespRedPackageDetail respRedPackageDetail = new RespRedPackageDetail();
            BeanUtils.copyProperties(e, respRedPackageDetail);
            return respRedPackageDetail;
        }).collect(Collectors.toList());
    }

    private TbUserWallet lockWallet(Integer userId) {
        TbUserWallet userWallet = tbUserWalletMapper.selectByPrimaryKeyForUpdate(userId);
        if (userWallet == null) {
            try {
                TbUserWallet wallet = new TbUserWallet();
                wallet.setUserId(userId);
                wallet.setChargeAmt(0L);
                wallet.setRedPackageAmt(BigDecimal.ZERO);
                wallet.setGiveAmt(0L);
                wallet.setBonusPoints(0L);
                Date now = new Date();
                wallet.setCreateTime(now);
                wallet.setUpdateTime(now);
                tbUserWalletMapper.insert(wallet);
            } catch (Exception e) {
                LOG.error(ExceptionUtils.getStackTrace(e));
            }
            userWallet = tbUserWalletMapper.selectByPrimaryKeyForUpdate(userId);
        }
        return userWallet;
    }


}
